#ifndef _KEY_CERT_H
#define _KEY_CERT_H

#include <openssl/obj_mac.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <stdint.h>

#define SM2_UID_SIZE_U 256

typedef enum _curve_id {
    CURVE_ID_TYPE_INVALID = 0,
    CURVE_ID_TYPE_MIN     = 0X1,
    CURVE_ID_TYPE_P256    = 0x1,
    CURVE_ID_TYPE_P384    = 0x2,
    CURVE_ID_TYPE_SM2_256 = 0x3,
    CURVE_ID_TYPE_MAX     = 0X3
} curve_id_t;

typedef struct _userid_u {
    unsigned short len;
    unsigned char  uid[SM2_UID_SIZE_U - sizeof(unsigned short)];
} userid_u;

#define SHA_256_SIZE               32
#define ECC_KEY_SIZE               32
#define CERT_ECC_MAX_KEY_SIZE      72
#define CERT_SM2_KEY_RESERVED_SIZE 624

/**
 *
 * @curve    - The curve identifier for the ECC public key.
 * @qx       - The x - coordinate of the public key point.
 * @qy       - The y - coordinate of the public key point
 */
typedef struct __attribute__((__packed__)) ecc_point_t {
    curve_id_t    curve;
    unsigned char qx[ECC_KEY_SIZE];
    unsigned char qy[ECC_KEY_SIZE];
} ecc_point;


/**
 * Total length must be 1028 bytes to match the cert.
 *
 * @curve    - The curve identifier for the SM2 public key.
 * @qx       - The x - coordinate of the public key point.
 * @qy       - The y - coordinate of the public key point
 * @userid   - The user ID
 * @reserved
 */
typedef struct __attribute__((__packed__)) sm2_pub_key_t {
    curve_id_t    curve;
    unsigned char qx[CERT_ECC_MAX_KEY_SIZE];
    unsigned char qy[CERT_ECC_MAX_KEY_SIZE];
    userid_u      userid;
    unsigned char reserved[CERT_SM2_KEY_RESERVED_SIZE];
} sm2_pubkey;

#define  REAL_ECDSA_RS_SIZE        32
#define  CERT_ECDSA_RS_SIZE        72
#define  CERT_ECDSA_SIG_SIZE       512
/**
 * Total length must be 512 bytes to match the cert.
 *
 * ECDSA Signature data.
 *
 * @r    - R component of the signature.
 * @s    - S component of the signature.
 * @rmbz - RESERVED. Must be zero!
 */
typedef struct __attribute__((__packed__)) ecdsa_sig_t {
    uint8_t r[CERT_ECDSA_RS_SIZE];
    uint8_t s[CERT_ECDSA_RS_SIZE];
    uint8_t rmbz[CERT_ECDSA_SIG_SIZE - 2*CERT_ECDSA_RS_SIZE];
} ecdsa_sig;


/**
 * CSV Certificate format.
 *
 * @version        - Cert version
 * @api_major      - Major API version
 * @api_minor      - Minor API version
 * @reserved_0
 * @reserved_1
 * @pub_key_usage  - Public Key Usage
 * @pub_key_algo   - Public Key Algorithm
 * @pub_key        - Public Key Itself
 * @sig_1_usage    - First Signature Usage
 * @sig_1_algo     - First Signature Algorithm
 * @sig_1          - First Signature Itself
 * @sig_2_usage    - Second Signature Usage
 * @sig_2_algo     - Second Signature Algothim
 * @sig_2          - Second Signature Itself
 */
typedef struct __attribute__ ((__packed__)) cert_t {
    uint32_t   version;
    uint8_t    api_major;
    uint8_t    api_minor;
    uint8_t    reserved_0;
    uint8_t    reserved_1;
    uint32_t   pub_key_usage;
    uint32_t   pub_key_algo;
    sm2_pubkey pub_key;
    uint32_t   sig_1_usage;
    uint32_t   sig_1_algo;
    ecdsa_sig  sig_1;
    uint32_t   sig_2_usage;
    uint32_t   sig_2_algo;
    ecdsa_sig  sig_2;
} csv_cert;

#endif
